#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

void handler(int signo)
{
    // sleep(1);
    cout << "我是一个进程，刚刚获取了一个信号: " << signo << endl;
    // exit(1);
}

static void showPending(sigset_t* pendings)
{
    for (int sig = 1; sig <= 31; sig++)
    {
        // 检测这31个信号是否在这个集合里
        if (sigismember(pendings, sig))
        {
            cout << '1';
        }
        else
        {
            cout << '0';
        }
    }
    cout << endl;
}

int cnt = 0;

int main()
{
    // 3. pending收到信号很快就递达了，所以先block，这样就能看到pending表里的信号了
    // 屏蔽二号信号
    sigset_t bsig, obsig;
    sigemptyset(&bsig);
    sigemptyset(&obsig);
    
    // 3.1 添加2号信号到信号屏蔽字中
    sigaddset(&bsig, 2);

    // 3.2 设置用户级的信号屏蔽字到内核中，让当前进程屏蔽掉2号信号
    sigprocmask(SIG_SETMASK, &bsig, &obsig);

    // 2. signal将二号信号进行自定义捕捉
    signal(2, handler);

    // 1. 不断获取当前进程的pending信号集
    // 表示当前进程的所有pending信号
    sigset_t pendings;

    while (true)
    {
        // 1.1 清空信号集
        sigemptyset(&pendings);

        // 1.2 获取当前进程（谁调用，获取谁）的pending信号集
        if (sigpending(&pendings) == 0)
        {
            // 获取成功
            // 1.3 打印一下当前进程的pending信号集
            showPending(&pendings);
        }
        sleep(1);
        
        // 先跑十秒钟，再解除屏蔽
        cnt++;
        if (cnt == 10)
        {
            cout << "解除对所有信号的block...." << endl;
            sigset_t sigs;
            sigemptyset(&sigs);
            sigaddset(&sigs, 2);
            // 只对2号解除屏蔽
            // sigprocmask(SIG_UNBLOCK, &sigs, nullptr);

            // 解除全部信号屏蔽
            sigprocmask(SIG_SETMASK, &obsig, nullptr);
        }
    }

    return 0;
}
